package com.lightkits.wms.domain.stocktransfer.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.lightkits.common.TransactionValidate;
import com.lightkits.common.db.entity.*;
import com.lightkits.common.service.CommonTransactionService;
import com.lightkits.framework.common.exception.LightKitsBizException;
import com.lightkits.framework.common.logging.Logger;
import com.lightkits.framework.common.logging.LoggerFactory;
import com.lightkits.framework.common.model.CheckResult;
import com.lightkits.framework.common.model.IResult;
import com.lightkits.framework.common.utility.object.ObjectUtil;
import com.lightkits.framework.common.utility.object.ParseUtil;
import com.lightkits.framework.common.utility.validate.IntegrityValidator;
import com.lightkits.framework.soa.client.id.IDServiceClient;
import com.lightkits.framework.soa.client.id.GetGlobalIDRequestType;
import com.lightkits.framework.soa.client.id.GetGlobalIDResponseType;
import com.lightkits.wms.domain.commons.service.WmsCommonsService;
import com.lightkits.wms.domain.saveonhand.models.OnhandParams;
import com.lightkits.wms.domain.saveonhand.service.UseParamsDomain;
import com.lightkits.wms.domain.stocktransfer.service.MiscellAdjustDomain;
import com.lightkits.wms.dto.onhand.model.OnhandDTO;
import com.lightkits.wms.dto.stocktransfer.model.MiscellAdjust;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

/**
 * MiscellAdjustDomainImpl
 *
 * @author jing.wei@hand-china.com
 * Created on 2019/4/24 12:10
 */
@Service
public class MiscellAdjustDomainImpl implements MiscellAdjustDomain {

    private final WmsCommonsService wmsCommonsService;
    private static final Logger LOGGER = LoggerFactory.getLogger(MiscellAdjustDomainImpl.class);

    private final UseParamsDomain useParamsDomain;
    private final CommonTransactionService service;
    private final IDServiceClient idAdapterService;

    @Autowired
    public MiscellAdjustDomainImpl(WmsCommonsService wmsCommonsService, UseParamsDomain useParamsDomain, CommonTransactionService service, IDServiceClient idAdapterService) {
        this.wmsCommonsService = wmsCommonsService;
        this.useParamsDomain = useParamsDomain;
        this.service = service;
        this.idAdapterService = idAdapterService;
    }

    private IResult checkParams(MiscellAdjust miscell) {
        try {
            IntegrityValidator.begin()
                    .validate(miscell.getEventRequestId(), "Event Request Id")
                    .validate(miscell.getOrgId(), "Organization Id")
                    .validate(miscell.getUomCode(), "Uom")
                    .validate(miscell.getItemId(), "Item Id")
                    .validate(miscell.getWarehouseId(), " Warehouse Id")
                    .validate(miscell.getOwnerType(), "Owner Type")
                    .validate(miscell.getDirection(), "Change Diraction")
                    .validate(miscell.getMoveTypeCode(), "Move Type Code")
                    .validate(miscell.getTransferQty(), "Transfer Quantity");
        } catch (LightKitsBizException e) {
            return e.result();
        }
        IResult result;
        result = wmsCommonsService.checkLocationParams(miscell.getWarehouseId(),
                miscell.getWmAreaId());
        if (!result.isSuccessful()) {
            return result;
        }
        result = wmsCommonsService.checkOwnerParams(miscell.getOwnerType(),
                miscell.getOwnerId());
        if (!result.isSuccessful()) {
            return result;
        }
        if (miscell.equals("OUT")) {
            result = wmsCommonsService.checkNegativestock(miscell.getWarehouseId(),
                    miscell.getWmAreaId(),
                    miscell.getTransferQty(),
                    miscell.getUomCode());
        }
        return result;
    }

    private CheckResult<OnhandDTO> convertParams(MiscellAdjust miscell, String direaction) {
        CheckResult<OnhandDTO> checkResult = new CheckResult<>();
        checkResult.setSuccessful(true);
        OnhandDTO params = new OnhandDTO();
        if (ObjectUtil.isNullOrEmpty(direaction)) {
            checkResult.setSuccessful(false);
            checkResult.setMessage("the direction is null");
            return checkResult;
        }
        if (!direaction.equals("OUT") && !direaction.equals("IN")) {
            checkResult.setSuccessful(false);
            checkResult.setMessage("the direction in undefiend");
            return checkResult;
        }
        try {
            params.setEventRequestId(miscell.getEventRequestId());
            params.setWorkerId(miscell.getWorkerId());
            params.setParentEventId(miscell.getParentEventId());
            params.setOrgId(miscell.getOrgId());
            params.setItemId(miscell.getItemId());
            params.setUomCode(miscell.getUomCode());
            params.setRemark(miscell.getRemark());
            params.setOwnerType(miscell.getOwnerType());
            params.setOwnerId(miscell.getOwnerId());
            params.setLotNumber(miscell.getLot());
            params.setChangeQuantity(miscell.getTransferQty());
            FndWmMoveTypeBase wmMoveTypeBase = new FndWmMoveTypeBase().selectOne(new EntityWrapper()
                    .eq(FndWmMoveTypeBase.MOVE_TYPE_CODE, miscell.getMoveTypeCode()));
            FndEventTypeBase eventTypeBase = new FndEventTypeBase().selectById(wmMoveTypeBase.getEventTypeId());
            params.setEventTypeCode(eventTypeBase.getEventTypeCode());
            params.setWarehouseId(miscell.getWarehouseId());
            params.setWmAreaId(miscell.getWmAreaId());
            params.setChangeDirection(miscell.getDirection());
            checkResult.setData(params);
        } catch (Exception e) {
            LOGGER.error("convertParams.error", e);
            throw new LightKitsBizException(e);
        }
        return checkResult;
    }

    private BdTransaction createTranscation(MiscellAdjust miscell, String direaction, Long transTypeId, Long moveTypeId) {
        BdTransaction trans = new BdTransaction();
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");

        try {
            GetGlobalIDRequestType idRequest = new GetGlobalIDRequestType();
            idRequest.setCount(1);
            GetGlobalIDResponseType idResponse = idAdapterService.getGlobalId(idRequest);
            Iterator<Long> sfIds = idResponse.getIds().iterator();
            FndTransactionTypeBase base = new FndTransactionTypeBase()
                    .selectById(transTypeId);
            trans.setTransactionTypeId(transTypeId);
            trans.setTransactionTypeCode(base.getTransactionTypeCode());
            trans.setOrganizationId(ParseUtil.tryLongWithException(miscell.getOrgId()));
            trans.setId(sfIds.next());
            trans.setItemId(ParseUtil.tryLongWithException(miscell.getItemId()));
            trans.setTransactionUom(miscell.getUomCode());
            trans.setTransactionDate(format.parse(format.format(new Date())));
            if (!ObjectUtil.isNullOrEmpty(miscell.getDocumentTypeId())) {
                trans.setDocumentTypeId(ParseUtil.tryLongWithException(miscell.getDocumentTypeId()));
            }
            if (!ObjectUtil.isNullOrEmpty(miscell.getDocumentLineId())) {
                trans.setDocumentLineId(ParseUtil.tryLongWithException(miscell.getDocumentLineId()));
            }
            if (!ObjectUtil.isNullOrEmpty(miscell.getDocumentId())) {
                trans.setDocumentId(ParseUtil.tryLongWithException(miscell.getDocumentId()));
            }
            trans.setDocumentTypeCode(miscell.getDocumentTypeCode());
            trans.setDocumentNum(miscell.getDocumentNum());
            trans.setLotNumber(miscell.getLot());
            format.applyPattern("HH:mm:ss");
            trans.setRemark(miscell.getRemark());
            trans.setTransactionTime(format.parse(format.format(new Date())));
            trans.setTransactionQty(new BigDecimal(miscell.getTransferQty()));
            trans.setWarehouseId(ParseUtil.tryLongWithException(miscell.getWarehouseId()));
            if (!ObjectUtil.isNullOrEmpty(miscell.getWmAreaId())) {
                trans.setWmAreaId(ParseUtil.tryLongWithException(miscell.getWmAreaId()));
            }
            trans.setWorkerId(ParseUtil.tryLongWithException(miscell.getWorkerId()));
            trans.setEventRequestId(miscell.getEventRequestId());
            FndWorker worker = new FndWorker().selectById(miscell.getWorkerId());
            trans.setWorkerNumber(worker.getWorkerNumber());
            trans.setTransactionReasonCode(moveTypeId);
        } catch (Exception e) {
            LOGGER.error("createTranscation.error", e);
            throw new LightKitsBizException(e);
        }
        return trans;

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public CheckResult<String> misCellAdjust(MiscellAdjust viewDTO) {
        CheckResult<String> checkResult = new CheckResult<>();
        checkResult.setSuccessful(true);
        if (ObjectUtil.isEmpty(viewDTO.getEventRequestId()) || viewDTO.getEventRequestId() == 0) {
            GetGlobalIDRequestType idRequest = new GetGlobalIDRequestType();
            idRequest.setCount(1);
            GetGlobalIDResponseType idResponse = idAdapterService.getGlobalId(idRequest);
            Iterator<Long> sfIds = idResponse.getIds().iterator();
            viewDTO.setEventRequestId(sfIds.next());
        }
        try {
            IResult result = this.checkParams(viewDTO);
            if (!result.isSuccessful()) {
                return result.fill(checkResult);
            }
            CheckResult<OnhandDTO> outOnhandParams = convertParams(viewDTO, viewDTO.getDirection());
            if (!outOnhandParams.isSuccessful()) {
                return IResult.fail(outOnhandParams.getMessage()).fill(checkResult);
            }

            CheckResult<OnhandParams> checkResultRes = useParamsDomain.getOnhandParams(outOnhandParams.getData());
            if (!checkResultRes.isSuccessful() || checkResultRes.getData() == null) {
                throw new LightKitsBizException(checkResultRes.getMessage());
            }
            CheckResult<String> resultOut = useParamsDomain.insertValue(checkResultRes.getData());
            if (!resultOut.isSuccessful() || ObjectUtil.isNullOrEmpty(resultOut.getData())) {
                throw new LightKitsBizException(resultOut.getMessage());
            }
            checkResult.setData(resultOut.getData());
            FndWmMoveTypeBase moveTypeBase = new FndWmMoveTypeBase()
                    .selectOne(new EntityWrapper()
                            .eq(FndWmMoveTypeBase.MOVE_TYPE_CODE, viewDTO.getMoveTypeCode()));
            if (!ObjectUtil.isEmpty(moveTypeBase.getTransactionTypeId())) {
                //create transcation
                List<BdTransaction> transactions = new ArrayList<>();
                BdTransaction positiveTrans = createTranscation(
                        viewDTO, viewDTO.getDirection(), moveTypeBase.getTransactionTypeId(), moveTypeBase.getId());
                transactions.add(positiveTrans);
                service.saveTransaction(transactions);
            }
        } catch (LightKitsBizException e)

        {
            e.printStackTrace();
        } catch (
                Exception e) {
            return IResult.fail("Save Onhand Quantity error").fill(checkResult);
        }
        return checkResult;

    }

}
